home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Deutsche Edition 2
/
Deutsche Edition 2.iso
/
mac
/
PROGRAMME
/
ARTAbrot 1.1 ƒ
/
BrotCode.c
< prev
next >
Wrap
Text File
|
1993-11-22
|
8KB
|
322 lines
/************************************************************************/
/* */
/* FILE: BrotCode.c -- Code for computing Mandelbrots. */
/* */
/* PURPOSE: Code to communicate with DSP to calculate Mandelbrots. */
/* */
/* AUTHOR: George T. Warner */
/* */
/* REVISIONS: */
/* 08/22/93 First version. */
/* */
/************************************************************************/
#include <Quickdraw.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "DSPManager.h"
#include "DSPConstants.h"
#include "BrotCode.h"
#include "ComUtil_ARTAbrot.h" /* Common */
#include "AB_Alert.h"
struct DSPCPUDeviceParamBlk pb, *pbPtr;
DSPTaskRefNum taskRefNum;
DSPModuleRefNum modRefNum;
DSPSectionRefNum BroBufRefNum;
/* Offscreen pixMap stuff. */
extern GWorldPtr offscreenGWorld; /* Off screen graphics world. */
extern Rect GWorldBounds; /* Boundaries of graphics world. */
int processing_brot = false;
short *data_mem = nil; /* Array for uploading Mandelbrot data into. */
unsigned long ypoint; /* Current y being processed. */
int xpix, ypix;
float fxdelta, fydelta;
double distance_per_pixel, fheight;
#define NumElements 128L
typedef struct
{
long Startflag;
long Doneflag;
long Points;
long Maxiter;
float Xstart;
float Delta;
float Ystart;
long Inited;
short OutputData[640];
}
MyPBuff;
MyPBuff *mypbuffptr;
pascal void fatalError(DSPMessagePtr errorBlockPtr)
{
#pragma unused (errorBlockPtr)
char tmp_string[256];
sprintf(tmp_string, "MessageActionProc called.");
AB_Alert(tmp_string);
}
void start_brot()
{
char tmp_string[256];
OSErr err;
SetPort(WPtr_ARTAbrot);
/* Get width of image to calculate. */
xpix = (WPtr_ARTAbrot->portRect.right-WPtr_ARTAbrot->portRect.left)-SCROLLBARWIDTH;
/* Get height of image to calculate. */
ypix = (WPtr_ARTAbrot->portRect.bottom-WPtr_ARTAbrot->portRect.top)-SCROLLBARWIDTH;
/* Find the distance between pixels. */
distance_per_pixel = fwidth/(double)xpix;
/* Find the height of the image. */
fheight = (double)ypix * distance_per_pixel;
pb.pbhDeviceIndex = 0; /* Just use device 0. */
pb.pbhClientPermission = kdspReadPermission; /* Not sure what this means. */
pb.pbhDeviceICON = nil; /* No icon desired. */
pb.pbhClientICON = nil;
pb.cpuClientMessageActionProc = fatalError;
BlockMove("\pARTAbrot", pb.pbhClientName, 32);
pbPtr = &pb;
/* Get information on DSP 0. */
if (DSPGetIndexedCPUDevice(pbPtr)) {
sprintf(tmp_string, "Failure: No DSPs attached!");
AB_Alert(tmp_string);
return;
}
/* Open device driver. */
if (DSPOpenCPUDevice(pbPtr)) {
sprintf(tmp_string, "Failure opening DSP device driver.");
AB_Alert(tmp_string);
return;
}
/* Create a new task structure. */
if (DSPNewTask(pbPtr, &fatalError, "\pMandelbrot", &taskRefNum)) {
sprintf(tmp_string, "Failure creating new task structure.");
AB_Alert(tmp_string);
goto close_device;
}
/* Load a module into the task structure. */
err = DSPLoadModule("\pmbrot", /* Load MBrot resource. */
taskRefNum, /* Pass task structure reference number. */
kdspAnyPositionInsert, /* Put it anywhere. */
(DSPModuleRefNum)NULL, /* Optional reference module number. */
&modRefNum, /* Pointer to get module reference number. */
NumElements); /* Scale multiplier (not sure about this yet). */
if (err) {
sprintf(tmp_string, "Failure loading MBrot module.");
AB_Alert(tmp_string);
goto dispose_task;
}
/* Insert Task into Task List */
if (DSPInsertTask(pbPtr, taskRefNum, kdspAnyPositionInsert, kdspTimeShare, (DSPTaskRefNum)NULL)) {
sprintf(tmp_string, "Failure inserting task.");
AB_Alert(tmp_string);
goto dispose_task;
}
/* Get section reference numbers for the parameter buffer. */
if (DSPGetSection(modRefNum,"\pbrobuf",&BroBufRefNum)) {
sprintf(tmp_string, "Failure getting parameter buffer reference number.");
AB_Alert(tmp_string);
goto remove_task;
}
/* Get pointer to parameter buffer. */
err = DSPGetSectionData(BroBufRefNum,(Ptr *)&mypbuffptr);
if (err) {
sprintf(tmp_string, "Failure getting parameter buffer pointer.");
AB_Alert(tmp_string);
goto remove_task;
}
/* Allocate buffer to hold one line of data. */
data_mem = (short *)calloc(xpix, sizeof(short));
if(!data_mem) {
sprintf(tmp_string, "Failure allocating data buffer.");
AB_Alert(tmp_string);
goto remove_task;
}
fydelta = fxdelta = fwidth/xpix;
/* Download left coordinate of image. */
mypbuffptr->Xstart = fxcenter-(fwidth/2);
mypbuffptr->Delta = fxdelta;
/* Download bottom coordinate of image. */
mypbuffptr->Ystart = fycenter-(fheight/2);
/* Tell num. of pixels to do. */
mypbuffptr->Points = xpix;
mypbuffptr->Maxiter = fiters;
/* Start with first line. */
mypbuffptr->Doneflag = 0;
mypbuffptr->Startflag = 0;
/* Start calculations! */
if (DSPSetTaskActive(taskRefNum)) {
sprintf(tmp_string, "Failure setting task active.");
AB_Alert(tmp_string);
goto quit_task;
}
/* Wait for DSP module to initialize. */
while (!mypbuffptr->Inited) {
/* Force stop waiting if user hits command-period. */
if (check_stop()) {
goto quit_task;
}
}
/* Start processing first line. */
mypbuffptr->Startflag = 1;
ypoint = 0;
processing_brot = true;
return;
quit_task:
if (data_mem)
free(data_mem);
remove_task:
/* Remove the Task */
if (DSPRemoveTask(taskRefNum)) {
ShowCursor();
sprintf(tmp_string, "Failure removing task.");
AB_Alert(tmp_string);
}
dispose_task:
/* Dispose the Task */
if (DSPDisposeTask(taskRefNum)) {
ShowCursor();
sprintf(tmp_string, "Failure disposing task.");
AB_Alert(tmp_string);
}
close_device:
/* Close the CPU Device */
if (DSPCloseCPUDevice(pbPtr)) {
ShowCursor();
sprintf(tmp_string, "Failure closing DSP driver.");
AB_Alert(tmp_string);
}
new_coordinates=FALSE;
ShowCursor();
}
void continue_brot()
{
Ptr base_addr;
long row_bytes; /* Used for PixMap calculations. */
Rect rect_to_copy;
unsigned char *pixel_address;
long xpoint;
if (!mypbuffptr->Doneflag) {
/* If no data to process, just return. */
return;
}
SetPort(WPtr_ARTAbrot);
/* Lock the offscreen GWorld. */
LockPixels(offscreenGWorld->portPixMap);
row_bytes = ((**(offscreenGWorld->portPixMap)).rowBytes) & 0x3fff;
base_addr = GetPixBaseAddr(offscreenGWorld->portPixMap);
/* Copy data from DSP buffer. */
BlockMove(mypbuffptr->OutputData, data_mem, xpix * sizeof(short));
ypoint++;
if (ypoint != ypix) { /* Don't start new line if we don't need it. */
/* Download new Y coordinate. */
mypbuffptr->Ystart = (fycenter-(fheight/2)) + (ypoint * fxdelta);
/* Acknowledge that last line was completed. */
mypbuffptr->Doneflag = 0;
/* Tell it to go. */
mypbuffptr->Startflag = 1;
}
/* Convert results to bytes for indexed color display. */
pixel_address = (unsigned char *)((unsigned long)base_addr + ((ypoint-1) * (unsigned long)row_bytes));
for (xpoint=0; xpoint < xpix; xpoint++)
*pixel_address++ = data_mem[xpoint];
SetRect(&rect_to_copy, GWorldBounds.left, GWorldBounds.top+ypoint-1, GWorldBounds.right, GWorldBounds.top+ypoint); /* left, top, right, bottom */
/* Display line on screen. */
CopyBits((BitMap *)*offscreenGWorld->portPixMap, &(WPtr_ARTAbrot->portBits), &(rect_to_copy), &(rect_to_copy), srcCopy, 0);
UnlockPixels(offscreenGWorld->portPixMap);
if (ypoint == ypix) {
/* If we are done, clean up. */
finish_brot();
}
}
void finish_brot()
{
char tmp_string[256];
processing_brot = false;
while (!mypbuffptr->Doneflag) {
/* Wait for last line to complete. */
if (check_stop()) {
/* If we can't wait or are hung, just get out. */
goto get_out_hard_way;
}
}
get_out_hard_way:
if (data_mem)
free(data_mem);
/* Remove the Task */
if (DSPRemoveTask(taskRefNum)) {
ShowCursor();
sprintf(tmp_string, "Failure removing task.");
AB_Alert(tmp_string);
}
/* Dispose the Task */
if (DSPDisposeTask(taskRefNum)) {
ShowCursor();
sprintf(tmp_string, "Failure disposing task.");
AB_Alert(tmp_string);
}
/* Close the CPU Device */
if (DSPCloseCPUDevice(pbPtr)) {
ShowCursor();
sprintf(tmp_string, "Failure closing DSP driver.");
AB_Alert(tmp_string);
}
new_coordinates=FALSE;
}